/*
 * LicenceManager.java Created on 2006��8��10��, ����1:29 by credible_zhang History:
 * ----------------------------------------------------------------------------- LicenceManager
 * 2006��8��10��, ����1:29 credible_zhang Create
 */

package com.phevos.common.util;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.security.InvalidKeyException;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.Signature;
import java.security.SignatureException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


public class LicenceManager
{
    private static final String LICENCE_PATH = "./licence/";

    private static final String PUB_KEY_FILE_NAME = "publicKey.key";

    private static final String LICENCE_FILE_NAME = "licence.key";

    private static final String DATE_FORMAT = "yyyy-MM-dd";

    private static final String KEY_PAIR = "DSA";

    private static final String SEP = "#@_@!";

    private static final int BITS = 512;

    private static Logger logger = LoggerFactory.getLogger(LicenceManager.class.getName());

    private static LicenceManager manager = null;

    private static String regInfo = null;

    private static String regIp = null;

    private static Date regDate = null;

    /**
     * Creates a new instance of LicenceManager ˽�л�ʵ��,��ֹ�ⲿ����ֱ�ӵ���
     */
    private LicenceManager()
    {
    }

    /**
     * ��ȡLicence������ʵ��
     * 
     * @return LicenceManager
     */
    public static LicenceManager getInstance()
    {
        if (manager == null)
            manager = new LicenceManager();
        return manager;
    }

    /**
     * ���������Ϣ��֤��
     * 
     * @param info String[]
     * @return boolean
     */
    public boolean validateLicence(String[] info)
    {
        // ��֤��������������
        if (info.length != 2 || info[0] == null || info[1] == null)
        {
            logger.error("���������Ϣ����ȫ,������֤����.");
            return false;
        }
 
        File pubFile = new File(LICENCE_PATH + PUB_KEY_FILE_NAME);
        File priFile = new File(LICENCE_PATH + LICENCE_FILE_NAME);
        if (!pubFile.exists() || !priFile.exists())
        {
            logger.error("Licence�ļ�������,���ش���.");
            return false;
        }
        if (regInfo == null || regIp == null || regDate == null)
        {
            // ��Licence�ļ��л�ȡ������Ϣ
            PublicKey pubkey = null;
            String tempInfoMsg = null;
            byte[] signed = null;
            try
            {
                ObjectInputStream pubKeyStream = new ObjectInputStream(new FileInputStream(pubFile));
                ObjectInputStream priKeyStrean = new ObjectInputStream(new FileInputStream(priFile));
                pubkey = (PublicKey)pubKeyStream.readObject();
                tempInfoMsg = (String)priKeyStrean.readObject();
                signed = (byte[])priKeyStrean.readObject();
            }
            catch (IOException ioe)
            {
                logger.error("����Ķ����ļ�.", ioe);
                return false;
            }
            catch (ClassNotFoundException cnfe)
            {
                logger.error("����Ķ������Ͷ�ȡ.", cnfe);
                return false;
            }
            if (pubkey == null || tempInfoMsg == null || signed == null || signed.length == 0)
                logger.error("Licence�е�ע����Ϣ����.");
            // ��֤ǩ��
            try
            {
                Signature signetcheck = Signature.getInstance(KEY_PAIR);
                signetcheck.initVerify(pubkey);
                signetcheck.update(tempInfoMsg.getBytes());
                if (signetcheck.verify(signed))
                {
                    String tmp = new String(new BASE64Decoder().decodeBuffer(tempInfoMsg));
                    String[] tmps = StringUtil.splitStr(tmp, SEP);
                    if (tmps == null || tmps.length != 3 || tmps[0] == null || tmps[1] == null
                            || tmps[2] == null)
                    {
                        logger.error("���������ǩ����Ϣ.");
                        return false;
                    }
                    regInfo = tmps[0].trim();
                    regIp = tmps[1].trim();
                    SimpleDateFormat format = new SimpleDateFormat(DATE_FORMAT);
                    try
                    {
                        regDate = format.parse(tmps[2].trim());
                    }
                    catch (ParseException pe)
                    {
                        logger.error("�����ע��ʱ����Ϣ.", pe);
                    }
                }
                else
                {
                    logger.error("�����ǩ��.");
                    return false;
                }
            }
            catch (NoSuchAlgorithmException ex)
            {
                logger.error("δ֪����Կ����㷨:" + KEY_PAIR, ex);
                return false;
            }
            catch (InvalidKeyException iex)
            {
                logger.error("�����Key", iex);
                return false;
            }
            catch (SignatureException sex)
            {
                logger.error("", sex);
                return false;
            }
        }
        // ��֤Licence�еļ�¼��Ϣ�Ƿ���������Ϣһ��
        if (!regInfo.equalsIgnoreCase(info[0]))
        {
            logger.error("ע����Ϣ[" + info[0] + "]����ȷ.");
            return false;
        }
        if (!regIp.equalsIgnoreCase(info[1]))
        {
            logger.error("�Ƿ���IP��ַ:" + info[1]);
            return false;
        }
        if (regDate.getTime() - System.currentTimeMillis() <= 0)
        {
            logger.error("�����Ѿ�����,�����¹���Licence.");
            return false;
        }
        return true;
    }

    /**
     * �������������Ϣ������Կ�ļ� �ڴ˷����в�Ҫʹ��Log4j��Ϊ�˷�������Main����ֱ�ӵ���,���е���Ϣ��Ҫֱ�Ӵ���Ļ��
     * 
     * @param info String[]
     */
    public void encrypto(String[] info)
    {
        if (info.length != 3 || info[0] == null || info[1] == null || info[2] == null)
        {
            printMessage("����������ȷ������������ȷ,����������.");
            return;
        }
        // �������Ϣ���л�
        StringBuffer sb = new StringBuffer("");
        for (int i = 0; i < info.length; i++)
        {
            sb.append(info[i]);
            if (i < info.length - 1)
                sb.append(SEP);
        }
        String regMsg = new BASE64Encoder().encode(sb.toString().getBytes());
        // ��Կ�Զ�������ʼ��
        KeyPairGenerator kpg = null;
        Signature signet = null;
        try
        {
            kpg = KeyPairGenerator.getInstance(KEY_PAIR);
            signet = Signature.getInstance(KEY_PAIR);
        }
        catch (NoSuchAlgorithmException ex)
        {
            System.out.println("δ֪����Կ����㷨:" + KEY_PAIR + "\n" + ex.toString());
            return;
        }
        // ��ʼ����������
        SecureRandom secrand = new SecureRandom();
        secrand.setSeed("bma china".getBytes());
        // ��ʼ����Կ������
        kpg.initialize(BITS, secrand);
        KeyPair keys = kpg.generateKeyPair(); // �����Կ��
        PublicKey pubkey = keys.getPublic(); // ��������Կ
        PrivateKey prikey = keys.getPrivate(); // ����˽����Կ
        ObjectOutputStream pubOut = null;
        ObjectOutputStream priOut = null;
        try
        {
            // ���˽����Կ��������Ϣ������Ϣ����
            signet.initSign(prikey);
            signet.update(regMsg.getBytes());
            byte[] signed = signet.sign();
            // ��֤�Ƿ����ļ���������ɾ��
            File pubFile = new File(LICENCE_PATH + PUB_KEY_FILE_NAME);
            File priFile = new File(LICENCE_PATH + LICENCE_FILE_NAME);
            File lPath = new File(LICENCE_PATH);
            if (!lPath.exists())
                lPath.mkdir();
            if (pubFile.exists())
                pubFile.delete();
            if (priFile.exists())
                priFile.delete();
            pubFile.createNewFile();
            priFile.createNewFile();
            // ����ļ�
            pubOut = new ObjectOutputStream(new FileOutputStream(pubFile));
            priOut = new ObjectOutputStream(new FileOutputStream(priFile));
            pubOut.writeObject(pubkey);
            priOut.writeObject(regMsg);
            priOut.writeObject(signed);
        }
        catch (InvalidKeyException iex)
        {
            System.out.println("�����Key:" + iex.getMessage());
            return;
        }
        catch (SignatureException sex)
        {
            System.out.println("ǩ����ɴ���:" + sex.getMessage());
            return;
        }
        catch (IOException ioe)
        {
            System.out.println("д�ļ��������.");;
            return;
        }
        finally
        {
            if (priOut != null)
            {
                try
                {
                    priOut.close();
                }
                catch (IOException e)
                {
                }
            }
            if (pubOut != null)
            {
                try
                {
                    pubOut.close();
                }
                catch (IOException e)
                {
                }
            }
        }
    }

    /**
     * ��ӡ��׼������Ϣ
     */
    private static void printMessage(String message)
    {
        System.out.println("======================================================");
        System.out.println("��ȷ���������:[ע�����] [IP��ַ] [��ֹʱ��(" + DATE_FORMAT + ")]");
        if (message != null)
            System.out.println(message);
        System.out.println("======================================================");
    }

    /**
     * �����з���,ͨ��˷������Բ���licence�ļ�
     * 
     * @param args String[]
     */
    public static void main(String[] args)
    {
        if (args.length != 3)
        {
            printMessage("�Ƿ��Ĳ�����:" + args.length);
            return;
        }
        SimpleDateFormat format = new SimpleDateFormat(DATE_FORMAT);
        try
        {
            format.parse(args[2].trim());
        }
        catch (ParseException pe)
        {
            printMessage("��Ч�ڽ�ֹʱ��:[" + args[2].trim() + "]����ϱ�׼��������.");
            return;
        }
        System.out.println("����ע����ϢΪ:[" + args[0] + "][" + args[1] + "][" + args[2] + "]");
        LicenceManager manager = LicenceManager.getInstance();
        manager.encrypto(args);
        // manager.validateLicence(new
        // String[]{"������j����ϵͳ�������޹�˾","192.168.0.63"});
    }
}
